
	/********************************************************************************

		@API
		Module: Crypto

		Hash:
			blob	md5						(data)
			blob	sha1					(data)
			blob	sha224				(data)
			blob	sha256				(data)
			blob	sha384				(data)
			blob	sha512				(data)
			blob	hmac					(data, key*, hash*)

		Keys:
			key		key						(password, size/options*)

		Chiper:
			blob 	aes.encrypt		(data, key, size/options*)
			blob 	aes.decrypt		(data, key, size/options*)

		Options:
			key (pbkdf2)		{ salt, size, count }
			aes							{ size, iv, mode, padding }
			hmac						{ hash }

		Note:
			data						s, al, Blob
			hmac hash				md5, sha1
			pbkdf2 options	{ salt, size, count }
			aes options 		{ size, iv, mode, padding }
			aes sizes				128,192,256

			iv (CBC, CFB, OFB, CTR)
				Initialization vector

			Block chiper modes:
   	 		ECB, CBC, CFB, OFB, CTR

			Block chiper padding (ECB, CBC):
		    pkcs7, ansiX923, iso10126, zero, no

	*******************************************************************************/

	//-------------------------------------------------------------------------------
	jsl.Crypto = (function() {
		try {
			var mod, k, Blob

			jsl.require("data")
			mod 	= new jsl.Module("jsl.Crypto")
			Blob 	= jsl.Data.Blob

			//md5 data
			//-------------------------------------------------------------------------------
			mod.__md5_r = [
				7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
				5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
				4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
				6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
   		]

			k = []
			for(var a = 0; a < 64; a++)
				k[a] = Math.floor(Math.abs(Math.sin(a + 1)) * Math.pow(2, 32)) >> 0

			mod.__md5_k = k

			//sha224/256 data
			//-------------------------------------------------------------------------------
			mod.__sha256_k = [
				0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
		   	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
		   	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
		   	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
		   	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
		   	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
		   	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
		   	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
		  ]

			//sha384/512 data
			//-------------------------------------------------------------------------------
			mod.__sha512_k = [
				[ 0x428a2f98, 0xd728ae22 ], [ 0x71374491, 0x23ef65cd ], [ 0xb5c0fbcf, 0xec4d3b2f ], [ 0xe9b5dba5, 0x8189dbbc ],
				[ 0x3956c25b, 0xf348b538 ], [ 0x59f111f1, 0xb605d019 ], [ 0x923f82a4, 0xaf194f9b ], [ 0xab1c5ed5, 0xda6d8118 ],
				[ 0xd807aa98, 0xa3030242 ], [ 0x12835b01, 0x45706fbe ], [ 0x243185be, 0x4ee4b28c ], [ 0x550c7dc3, 0xd5ffb4e2 ],
				[ 0x72be5d74, 0xf27b896f ], [ 0x80deb1fe, 0x3b1696b1 ], [ 0x9bdc06a7, 0x25c71235 ], [ 0xc19bf174, 0xcf692694 ],
				[ 0xe49b69c1, 0x9ef14ad2 ], [ 0xefbe4786, 0x384f25e3 ], [ 0x0fc19dc6, 0x8b8cd5b5 ], [ 0x240ca1cc, 0x77ac9c65 ],
				[ 0x2de92c6f, 0x592b0275 ], [ 0x4a7484aa, 0x6ea6e483 ], [ 0x5cb0a9dc, 0xbd41fbd4 ], [ 0x76f988da, 0x831153b5 ],
				[ 0x983e5152, 0xee66dfab ], [ 0xa831c66d, 0x2db43210 ], [ 0xb00327c8, 0x98fb213f ], [ 0xbf597fc7, 0xbeef0ee4 ],
				[ 0xc6e00bf3, 0x3da88fc2 ], [ 0xd5a79147, 0x930aa725 ], [ 0x06ca6351, 0xe003826f ], [ 0x14292967, 0x0a0e6e70 ],
				[ 0x27b70a85, 0x46d22ffc ], [ 0x2e1b2138, 0x5c26c926 ], [ 0x4d2c6dfc, 0x5ac42aed ], [ 0x53380d13, 0x9d95b3df ],
				[ 0x650a7354, 0x8baf63de ], [ 0x766a0abb, 0x3c77b2a8 ], [ 0x81c2c92e, 0x47edaee6 ], [ 0x92722c85, 0x1482353b ],
				[ 0xa2bfe8a1, 0x4cf10364 ], [ 0xa81a664b, 0xbc423001 ], [ 0xc24b8b70, 0xd0f89791 ], [ 0xc76c51a3, 0x0654be30 ],
				[ 0xd192e819, 0xd6ef5218 ], [ 0xd6990624, 0x5565a910 ], [ 0xf40e3585, 0x5771202a ], [ 0x106aa070, 0x32bbd1b8 ],
				[ 0x19a4c116, 0xb8d2d0c8 ], [ 0x1e376c08, 0x5141ab53 ], [ 0x2748774c, 0xdf8eeb99 ], [ 0x34b0bcb5, 0xe19b48a8 ],
				[ 0x391c0cb3, 0xc5c95a63 ], [ 0x4ed8aa4a, 0xe3418acb ], [ 0x5b9cca4f, 0x7763e373 ], [ 0x682e6ff3, 0xd6b2b8a3 ],
				[ 0x748f82ee, 0x5defb2fc ], [ 0x78a5636f, 0x43172f60 ], [ 0x84c87814, 0xa1f0ab72 ], [ 0x8cc70208, 0x1a6439ec ],
				[ 0x90befffa, 0x23631e28 ], [ 0xa4506ceb, 0xde82bde9 ], [ 0xbef9a3f7, 0xb2c67915 ], [ 0xc67178f2, 0xe372532b ],
				[ 0xca273ece, 0xea26619c ], [ 0xd186b8c7, 0x21c0c207 ], [ 0xeada7dd6, 0xcde0eb1e ], [ 0xf57d4f7f, 0xee6ed178 ],
				[ 0x06f067aa, 0x72176fba ], [ 0x0a637dc5, 0xa2c898a6 ], [ 0x113f9804, 0xbef90dae ], [ 0x1b710b35, 0x131c471b ],
				[ 0x28db77f5, 0x23047d84 ], [ 0x32caab7b, 0x40c72493 ], [ 0x3c9ebe0a, 0x15c9bebc ], [ 0x431d67c4, 0x9c100d4c ],
				[ 0x4cc5d4be, 0xcb3e42b6 ], [ 0x597f299c, 0xfc657e2a ], [ 0x5fcb6fab, 0x3ad6faec ], [ 0x6c44198c, 0x4a475817 ]
			]

			//aes
			//-------------------------------------------------------------------------------
			mod.aes 			= { __name: "jsl.Crypto.aes" }
			mod.aes.__sbx = [
				0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
				0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
				0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
				0x04, 0xc7,	0x23,	0xc3,	0x18,	0x96,	0x05,	0x9a,	0x07,	0x12,	0x80,	0xe2,	0xeb,	0x27,	0xb2,	0x75,
				0x09,	0x83,	0x2c,	0x1a,	0x1b,	0x6e,	0x5a,	0xa0,	0x52,	0x3b,	0xd6,	0xb3,	0x29,	0xe3,	0x2f,	0x84,
				0x53,	0xd1,	0x00,	0xed,	0x20,	0xfc,	0xb1,	0x5b,	0x6a,	0xcb,	0xbe,	0x39,	0x4a,	0x4c,	0x58,	0xcf,
				0xd0,	0xef,	0xaa,	0xfb,	0x43,	0x4d,	0x33,	0x85,	0x45,	0xf9,	0x02,	0x7f,	0x50,	0x3c,	0x9f,	0xa8,
				0x51,	0xa3,	0x40,	0x8f,	0x92,	0x9d,	0x38,	0xf5,	0xbc,	0xb6,	0xda,	0x21,	0x10,	0xff,	0xf3,	0xd2,
				0xcd,	0x0c,	0x13,	0xec,	0x5f,	0x97,	0x44,	0x17,	0xc4,	0xa7,	0x7e,	0x3d,	0x64,	0x5d,	0x19,	0x73,
				0x60,	0x81,	0x4f,	0xdc,	0x22,	0x2a,	0x90,	0x88,	0x46,	0xee,	0xb8,	0x14,	0xde,	0x5e,	0x0b,	0xdb,
				0xe0,	0x32,	0x3a,	0x0a,	0x49,	0x06,	0x24,	0x5c,	0xc2,	0xd3,	0xac,	0x62,	0x91,	0x95,	0xe4,	0x79,
				0xe7,	0xc8,	0x37,	0x6d,	0x8d,	0xd5,	0x4e,	0xa9,	0x6c,	0x56,	0xf4,	0xea,	0x65,	0x7a,	0xae,	0x08,
				0xba,	0x78,	0x25,	0x2e,	0x1c,	0xa6,	0xb4,	0xc6,	0xe8,	0xdd,	0x74,	0x1f,	0x4b,	0xbd,	0x8b,	0x8a,
				0x70,	0x3e,	0xb5,	0x66,	0x48,	0x03,	0xf6,	0x0e,	0x61,	0x35,	0x57,	0xb9,	0x86,	0xc1,	0x1d,	0x9e,
				0xe1,	0xf8,	0x98,	0x11,	0x69,	0xd9,	0x8e,	0x94,	0x9b,	0x1e,	0x87,	0xe9,	0xce,	0x55,	0x28,	0xdf,
				0x8c,	0xa1,	0x89,	0x0d,	0xbf,	0xe6,	0x42,	0x68,	0x41,	0x99,	0x2d,	0x0f,	0xb0,	0x54,	0xbb,	0x16
			]

		mod.aes.__sbxi = [
				0x52,	0x09,	0x6a,	0xd5, 0x30,	0x36,	0xa5,	0x38,	0xbf,	0x40,	0xa3,	0x9e,	0x81,	0xf3,	0xd7,	0xfb,
				0x7c,	0xe3,	0x39,	0x82,	0x9b,	0x2f,	0xff,	0x87,	0x34,	0x8e,	0x43,	0x44,	0xc4,	0xde,	0xe9,	0xcb,
				0x54,	0x7b,	0x94,	0x32,	0xa6,	0xc2,	0x23,	0x3d,	0xee,	0x4c,	0x95,	0x0b,	0x42,	0xfa,	0xc3,	0x4e,
				0x08, 0x2e,	0xa1,	0x66,	0x28,	0xd9,	0x24,	0xb2,	0x76,	0x5b,	0xa2,	0x49,	0x6d,	0x8b,	0xd1,	0x25,
				0x72, 0xf8,	0xf6,	0x64,	0x86,	0x68,	0x98,	0x16,	0xd4,	0xa4,	0x5c,	0xcc,	0x5d,	0x65,	0xb6,	0x92,
				0x6c, 0x70,	0x48,	0x50,	0xfd,	0xed,	0xb9,	0xda,	0x5e,	0x15,	0x46,	0x57,	0xa7,	0x8d,	0x9d,	0x84,
				0x90, 0xd8,	0xab,	0x00,	0x8c,	0xbc,	0xd3,	0x0a,	0xf7,	0xe4,	0x58,	0x05,	0xb8,	0xb3,	0x45,	0x06,
				0xd0, 0x2c,	0x1e,	0x8f,	0xca,	0x3f,	0x0f,	0x02,	0xc1,	0xaf,	0xbd,	0x03,	0x01,	0x13,	0x8a,	0x6b,
				0x3a, 0x91,	0x11,	0x41,	0x4f,	0x67,	0xdc,	0xea,	0x97,	0xf2,	0xcf,	0xce,	0xf0,	0xb4,	0xe6,	0x73,
				0x96, 0xac,	0x74,	0x22,	0xe7,	0xad,	0x35,	0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
				0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
				0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
				0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
				0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
				0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
				0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
			]

			mod.aes.__2 = [
				0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
				0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
				0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
				0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
				0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,
				0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
				0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,
				0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,
				0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05,
				0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25,
				0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45,
				0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65,
				0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85,
				0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5,
				0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5,
				0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5
			]

			mod.aes.__3 = [
				0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11,
				0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21,
				0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71,
				0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41,
				0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1,
				0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1,
				0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1,
				0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81,
				0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a,
				0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba,
				0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea,
				0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda,
				0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a,
				0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a,
				0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a,
				0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a
			]

			mod.aes.__9 = [
				0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,
				0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7,
				0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,
				0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc,
				0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01,
				0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91,
				0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a,
				0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa,
				0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b,
				0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b,
				0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0,
				0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30,
				0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed,
				0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d,
				0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6,
				0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46
			]

			mod.aes.__B = [
				0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69,
				0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9,
				0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12,
				0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2,
				0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f,
				0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f,
				0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4,
				0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54,
				0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e,
				0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e,
				0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5,
				0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55,
				0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68,
				0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8,
				0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13,
				0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3
			]

			mod.aes.__D = [
				0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b,
				0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b,
				0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0,
				0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20,
				0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26,
				0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6,
				0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d,
				0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d,
				0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91,
				0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41,
				0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a,
				0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa,
				0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc,
				0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c,
				0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47,
				0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97
			]

			mod.aes.__E = [
				0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a,
				0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba,
				0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81,
				0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61,
				0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7,
				0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17,
				0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c,
				0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc,
				0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b,
				0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb,
				0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0,
				0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20,
				0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6,
				0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56,
				0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d,
				0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d
			]

			mod.aes.__rc = [
       0x00000000,
       0x01000000,
       0x02000000,
       0x04000000,
       0x08000000,
       0x10000000,
       0x20000000,
       0x40000000,
       0x80000000,
       0x1b000000,
       0x36000000
      ]

			//Options
			//-------------------------------------------------------------------------------
			mod.option("hmac")
			mod.option("hmac.hash", {
				dvalue: 		"sha1",
				validator:	"si(sha1,md5)",
				setter:			function(nv, ov, id) { return nv.toLowerCase() }
			})
			//-------------------------------------------------------------------------------
			mod.option("key")
			mod.option("key.salt", {
				dvalue: 		new Blob("www.jsliquid.com"),
				validator:	"binary+",
				setter:	function(nv, ov, id) { return new Blob(nv) }
			})
			//-------------------------------------------------------------------------------
			mod.option("key.count", {
				dvalue: 		100,
				validator:	"i[1,4294967295]",
				setter:			function(nv, ov, id) { return +nv }
			})
			//-------------------------------------------------------------------------------
			mod.option("key.size", {
				dvalue: 		16,
				validator:	"i[1,1310700]",
				setter:			function(nv, ov, id) { return +nv }
			})
			//-------------------------------------------------------------------------------
			mod.option("aes")
			mod.option("aes.mode", {
				dvalue: 		"CTR",
				validator:	"si(ECB,CBC,CFB,OFB,CTR)",
				setter: 		function(nv, ov, id) { return nv.toUpperCase() }
			})
			//-------------------------------------------------------------------------------
			mod.option("aes.padding", {
				dvalue: 		"pkcs7",
				validator:	"si(pkcs7,ansiX923,iso10126,zero,no)",
				setter: function(nv, ov, id) { return nv.toLowerCase() }
			})
			//-------------------------------------------------------------------------------
			mod.option("aes.iv", {
				dvalue:			new Blob("www.jsliquid.com"),
				validator:	"binary+",
				setter: 		function(nv, ov, id) { return new Blob(nv) }
			})
			//-------------------------------------------------------------------------------
			mod.option("aes.size", {
				dvalue: 		128,
				validator:	"ns(128,192,256)",
				setter: 		function(nv, ov, id) { return +nv }
			})

			//messages
			//-------------------------------------------------------------------------------
			jsl.message("crypto.aes.EmptyKey",			"<key> empty key")
			jsl.message("crypto.aes.DecryptError",	"decryption failed. One or more AES options are not the same specified at encryption time")
			jsl.message("crypto.aes.BadPadding",		"impossible encrypt the current message in $ mode without execute a padding " +
																								"because the message size is not a multiple of 16 bytes")

			return mod
		}
		catch(e) {
			jsl.throwError(e, "jsl.Crypto")
		}
	})()
	//-------------------------------------------------------------------------------
	jsl.Crypto.md5 = function(data) {
		try {
			var a, b, c, d, f, g, ds, n1, n2, r, k, a1, l, bl, h0, h1, h2, h3, wg//!
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(data, "t(s,al,Blob)", "data")//!

			ds	= jsl.Data.Blob.toArray(data)
			r		= this.__md5_r
			k 	= this.__md5_k
			bl	= ds.length * 8

			//@sys: Opera Mobile 12.1 - (l % 1024 !== 448) freeze (slow down) the execution
			//of the next instructions ex: 1 minute to execute the below [for]
			for(l = bl + 1; l - ~~(l / 512) * 512 !== 448; l++);
			l /= 8

			ds[ds.length] = 128
			ds[l]					= bl & 0xFF
			ds[l + 1]			= bl >> 8 	& 0xFF
			ds[l + 2]			= bl >> 16	& 0xFF
			ds[l + 3]			= bl >>> 24

			h0 = 0x67452301
			h1 = 0xefcdab89
			h2 = 0x98badcfe
			h3 = 0x10325476

			for(var i0 = 0; i0 < l; i0 += 64) {

				a = h0
				b = h1
				c = h2
				d = h3

				for(var i1 = 0; i1 < 64; i1++) {

					if(i1 < 16) {
						f = ((b & c) | (~b & d)) >>> 0
						g = 4 * i1
					}
					else if(i1 < 32) {
		 				f = ((d & b) | (~d & c)) >>> 0
            g = 4 * ((5 * i1 + 1) % 16)
					}
					else if(i1 < 48) {
						f = (b ^ c ^ d) >>> 0
            g = 4 * ((3 * i1 + 5) % 16)
					}
					else {
						f = (c ^ (b | ~d)) >>> 0
            g = 4 * ((7 * i1) % 16)
					}

					n1 	= d
	        d 	= c
	        c 	= b
	        n2	= i0 + g
	        wg	= (ds[n2] | ds[n2 + 1] << 8 | ds[n2 + 2] << 16 | ds[n2 + 3] << 24) >>> 0
	        a1	= a + f + k[i1] + wg
	        b 	= (b + ((a1 << r[i1] | a1 >>> (32 - r[i1])))) >>> 0
	        a 	= n1
				}

				h0 += a
				h1 += b
				h2 += c
				h3 += d
			}

			ds = [
			      h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24,
			      h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24,
			      h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24,
			      h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24
			     ]

			return new jsl.Data.Blob(ds)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.sha1 = function(data) {
		try {
			var bs, bl, l, h0, h1, h2, h3, h4, i, i2, i3, w, a, b, c, d, e, n, f, k//!
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(data, "t(s,al,Blob)", "data")//!

			bs = jsl.Data.Blob.toArray(data)
			bl = bs.length * 8

			//@sys: Opera Mobile 12.1 - (l % 1024 !== 448) freeze (slow down) the execution
			//of the next instructions ex: 1 minute to execute the below [for]
			for(l = bl + 1; l - ~~(l / 512) * 512 !== 448; l++);
			l /= 8

			bs[bs.length] = 128
			bs[l + 4]			= bl >>> 24
			bs[l + 5]			= bl >>> 16	& 0xff
			bs[l + 6]			= bl >>>	8 & 0xff
			bs[l + 7]			= bl 				& 0xff

			h0 	= 0x67452301
			h1 	= 0xefcdab89
			h2 	= 0x98badcfe
			h3 	= 0x10325476
			h4 	= 0xc3d2e1f0
			w		= []

			for(i = 0; i < l; i += 64) {

				n = i + 64
				for(i2 = i, i3 = 0; i2 < n; i2 += 4)
					w[i3++] = (bs[i2] << 24 | bs[i2 + 1] << 16 | bs[i2 + 2] << 8 | bs[i2 + 3]) >>> 0

				for(; i3 < 80; i3++) {
					w[i3] = w[i3 - 3] ^ w[i3 - 8] ^ w[i3 - 14] ^ w[i3 - 16]
					w[i3] = (w[i3] << 1 | w[i3] >>> 31) >>> 0
				}

				a = h0
				b = h1
				c = h2
				d = h3
				e = h4

				for(i2 = 0; i2 < 80; i2++) {

					if(i2 < 20) {
						f = b & c | ~b & d
						k = 0x5a827999
					}
					else if(i2 < 40) {
		 				f = b ^ c ^ d
            k = 0x6ed9eba1
					}
					else if(i2 < 60) {
						f = b & c | b & d | c & d
            k = 0x8f1bbcdc
					}
					else {
						f = b ^ c ^ d
            k = 0xca62c1d6
					}

					n = ((a << 5 | a >>> 27) >>> 0) + (f >>> 0) + e + k + w[i2]
	        e = d
	        d = c
	        c	= (b << 30 | b >>> 2) >>> 0
	        b	= a
	        a	= n >>> 0
				}

				h0 += a
				h1 += b
				h2 += c
				h3 += d
				h4 += e
			}

			return new jsl.Data.Blob([
	      h0 >>> 24, h0 >>> 16 & 0xff, h0 >> 8 & 0xff, h0 & 0xff,
	      h1 >>> 24, h1 >>> 16 & 0xff, h1 >> 8 & 0xff, h1 & 0xff,
	      h2 >>> 24, h2 >>> 16 & 0xff, h2 >> 8 & 0xff, h2 & 0xff,
	      h3 >>> 24, h3 >>> 16 & 0xff, h3 >> 8 & 0xff, h3 & 0xff,
	      h4 >>> 24, h4 >>> 16 & 0xff, h4 >> 8 & 0xff, h4 & 0xff
			])
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.sha224 = function(data) {
		try {
			this.__sha224 = true
			return this.__sha256.apply(this, arguments)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.sha256 = function(data) {
		try {
			this.__sha224 = false
			return this.__sha256.apply(this, arguments)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.__sha256 = function(data) {
		var bs, bl, l, h0, h1, h2, h3, h4, h5, h6, h7, i, i2, i3, w, a, b, c, d, e, f, g, h, t1, t2, k, s0, s1, n, s224//!
		if(arguments.length !== 1)	throw jsl.ParamError()
		jsl.validate(data, "t(s,al,Blob)", "data")//!

		bs = jsl.Data.Blob.toArray(data)
		bl = bs.length * 8

		//@sys: Opera Mobile 12.1 - (l % 1024 !== 448) freeze (slow down) the execution
		//of the next instructions ex: 1 minute to execute the below [for]
		for(l = bl + 1; l - ~~(l / 512) * 512 !== 448; l++);
		l /= 8

		bs[bs.length] = 128
		bs[l + 4]			= bl >>> 24
		bs[l + 5]			= bl >>> 16	& 0xff
		bs[l + 6]			= bl >>>	8 & 0xff
		bs[l + 7]			= bl 				& 0xff

		s224 = this.__sha224
		if(s224) {
			h0 = 0xc1059ed8
			h1 = 0x367cd507
			h2 = 0x3070dd17
			h3 = 0xf70e5939
			h4 = 0xffc00b31
			h5 = 0x68581511
			h6 = 0x64f98fa7
			h7 = 0xbefa4fa4
		}
		else {
			h0 = 0x6a09e667
			h1 = 0xbb67ae85
			h2 = 0x3c6ef372
			h3 = 0xa54ff53a
			h4 = 0x510e527f
			h5 = 0x9b05688c
			h6 = 0x1f83d9ab
			h7 = 0x5be0cd19
		}

		k	= this.__sha256_k
		w	= []

		for(i = 0; i < l; i += 64) {

			n = i + 64
			for(i2 = i, i3 = 0; i2 < n; i2 += 4)
				w[i3++] = (bs[i2] << 24 | bs[i2 + 1] << 16 | bs[i2 + 2] << 8 | bs[i2 + 3]) >>> 0

			for(; i3 < 64; i3++) {
				t1		= w[i3 - 15]
				t2		= w[i3 - 2]
				s0 		= (t1 >>> 7 	| t1 << 25) ^ (t1 >>> 18 | t1 << 14) ^ t1 >>> 3
				s1 		= (t2 >>> 17 	| t2 << 15) ^ (t2 >>> 19 | t2 << 13) ^ t2 >>> 10
				w[i3] = (w[i3 - 16] + (s0 >>> 0) + w[i3 - 7] + (s1 >>> 0)) >>> 0
			}

			a = h0
			b = h1
			c = h2
			d = h3
			e = h4
			f = h5
			g = h6
			h = h7

			for(i2 = 0; i2 < 64; i2++) {

				s0 = ((a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10))	>>> 0
				s1 = ((e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7)) 	>>> 0

      	t1 = (h + s1 + ((e & f ^ ~e & g) >>> 0) + k[i2] + w[i2]) >>> 0
				t2 = (s0 + (a & b ^ a & c ^ b & c) >>> 0) >>> 0

        h = g
        g = f
        f = e
        e = d + t1
        d = c
        c = b
        b = a
        a = t1 + t2
			}

			h0 += a
			h1 += b
			h2 += c
			h3 += d
			h4 += e
			h5 += f
			h6 += g
			h7 += h
		}

		h = [
      h0 >>> 24, h0 >>> 16 & 0xff, h0 >> 8 & 0xff, h0 & 0xff,
      h1 >>> 24, h1 >>> 16 & 0xff, h1 >> 8 & 0xff, h1 & 0xff,
      h2 >>> 24, h2 >>> 16 & 0xff, h2 >> 8 & 0xff, h2 & 0xff,
      h3 >>> 24, h3 >>> 16 & 0xff, h3 >> 8 & 0xff, h3 & 0xff,
      h4 >>> 24, h4 >>> 16 & 0xff, h4 >> 8 & 0xff, h4 & 0xff,
      h5 >>> 24, h5 >>> 16 & 0xff, h5 >> 8 & 0xff, h5 & 0xff,
      h6 >>> 24, h6 >>> 16 & 0xff, h6 >> 8 & 0xff, h6 & 0xff
		]

		if(!s224) h.push(h7 >>> 24, h7 >>> 16 & 0xff, h7 >> 8 & 0xff, h7 & 0xff)
		return new jsl.Data.Blob(h)
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.sha384 = function(data) {
		try {
			this.__sha384 = true
			return this.__sha512.apply(this, arguments)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.sha512 = function(data) {
		try {
			this.__sha384 = false
			return this.__sha512.apply(this, arguments)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.__sha512 = function(data) {
		var bs, bl, l, h0, h1, h2, h3, h4, h5, h6, h7, i, i2, i3, w, a, b, c, d, e, n, f, g, h, t1, k, s384, d0, d1, d2, v0, v1//!
		if(arguments.length !== 1)	throw jsl.ParamError()
		jsl.validate(data, "t(s,al,Blob)", "data")//!

		bs = jsl.Data.Blob.toArray(data)
		bl = bs.length * 8

		//@sys: Opera Mobile 12.1 - (l % 1024 !== 896) freeze (slow down) the execution
		//of the next instructions ex: 1 minute to execute the below [for]
		for(l = bl + 1; l - ~~(l / 1024) * 1024 !== 896; l++);
		l /= 8

		bs[bs.length] = 128
		bs[l + 12]		= bl >>> 24
		bs[l + 13]		= bl >>> 16	& 0xff
		bs[l + 14]		= bl >>>	8 & 0xff
		bs[l + 15]		= bl 				& 0xff

		s384 = this.__sha384

		if(s384) {
			h0 = [ 0xcbbb9d5d, 0xc1059ed8 ]
			h1 = [ 0x629a292a, 0x367cd507 ]
			h2 = [ 0x9159015a, 0x3070dd17 ]
			h3 = [ 0x152fecd8, 0xf70e5939 ]
			h4 = [ 0x67332667, 0xffc00b31 ]
			h5 = [ 0x8eb44a87, 0x68581511 ]
			h6 = [ 0xdb0c2e0d, 0x64f98fa7 ]
			h7 = [ 0x47b5481d, 0xbefa4fa4 ]
		}
		else {
			h0 = [ 0x6a09e667, 0xf3bcc908 ]
			h1 = [ 0xbb67ae85, 0x84caa73b ]
			h2 = [ 0x3c6ef372, 0xfe94f82b ]
			h3 = [ 0xa54ff53a, 0x5f1d36f1 ]
			h4 = [ 0x510e527f, 0xade682d1 ]
			h5 = [ 0x9b05688c, 0x2b3e6c1f ]
			h6 = [ 0x1f83d9ab, 0xfb41bd6b ]
			h7 = [ 0x5be0cd19, 0x137e2179 ]
		}

		k		= this.__sha512_k
		w		= []
		d0	= []
		d1	= []
		d2	= []
		t1	= []

		//@sys: Opera 11.52, Opera Mobile 12.1 -> NaN and >>> issue -> Note.txt
		for(i = 0; i < l; i += 128) {

			n = i + 128
			for(i2 = i, i3 = 0; i2 < n; i2 += 8)
				w[i3++] = [ bs[i2 + 0] << 24 | bs[i2 + 1] << 16 | bs[i2 + 2] << 8 | bs[i2 + 3],
										bs[i2 + 4] << 24 | bs[i2 + 5] << 16 | bs[i2 + 6] << 8 | bs[i2 + 7] ]

			for(; i3 < 80; i3++) {

				v0		= w[i3 - 15][0]
				v1		= w[i3 - 15][1]
				d0[0] = (v1 << 31 | v0 >>> 1) ^ (v1 << 24 | v0 >>> 8) ^ v0 >>> 7
				d0[1] = (v0 << 31 | v1 >>> 1) ^ (v0 << 24 | v1 >>> 8) ^ (v0 << 25 | v1 >>> 7)
				d0[0] >>>= NaN
				d0[1] >>>= NaN

				v0		= w[i3 - 2][0]
				v1		= w[i3 - 2][1]
				d1[0] = (v1 << 13 | v0 >>> 19) ^ (v0 << 3 | v1 >>> 29) ^ v0 >>> 6
				d1[1] = (v0 << 13 | v1 >>> 19) ^ (v1 << 3 | v0 >>> 29) ^ (v0 << 26 | v1 >>> 6)
				d1[0] >>>= NaN
				d1[1] >>>= NaN

				d2[0] = d0[0] + d1[0] >>> NaN
				d2[1] = d0[1] + d1[1] >>> NaN
				if(d2[1] < d0[1] || d2[1] < d1[1]) d2[0] = ++d2[0] >>> NaN

				d1[0] = d2[0] + w[i3 - 7][0] >>> NaN
				d1[1] = d2[1] + w[i3 - 7][1] >>> NaN
				if(d1[1] < d2[1] || d1[1] < w[i3 - 7][1]) d1[0] = ++d1[0] >>> NaN

				w[i3]			= w[i3] || []
				w[i3][0] 	= d1[0] + w[i3 - 16][0] >>> NaN
				w[i3][1] 	= d1[1] + w[i3 - 16][1] >>> NaN
				if(w[i3][1] < d1[1] || w[i3][1] < w[i3 - 16][1]) w[i3][0] = ++w[i3][0] >>> NaN
			}

			a = [ h0[0], h0[1] ]
			b = [ h1[0], h1[1] ]
			c = [ h2[0], h2[1] ]
			d = [ h3[0], h3[1] ]
			e = [ h4[0], h4[1] ]
			f = [ h5[0], h5[1] ]
			g = [ h6[0], h6[1] ]
			h = [ h7[0], h7[1] ]

			for(i2 = 0; i2 < 80; i2++) {

				d0[0] = e[0] & f[0] ^ ~e[0] & g[0]
				d0[1] = e[1] & f[1] ^ ~e[1] & g[1]
				d0[0] >>>= NaN
				d0[1] >>>= NaN

				d1[0] = (e[1] << 18 | e[0] >>> 14) ^ (e[1] << 14 | e[0] >>> 18) ^ (e[0] << 23 | e[1] >>> 9)
				d1[1] = (e[0] << 18 | e[1] >>> 14) ^ (e[0] << 14 | e[1] >>> 18) ^ (e[1] << 23 | e[0] >>> 9)
				d1[0] >>>= NaN
				d1[1] >>>= NaN

				d2[0] = d0[0] + d1[0] >>> NaN
				d2[1] = d0[1] + d1[1] >>> NaN
				if(d2[1] < d0[1] || d2[1] < d1[1]) d2[0] = (d2[0] + 1) >>> NaN

				d0[0] = d2[0] + h[0] >>> NaN
				d0[1] = d2[1] + h[1] >>> NaN
				if(d0[1] < d2[1] || d0[1] < h[1]) d0[0] = ++d0[0] >>> NaN

				d1[0] = d0[0] + k[i2][0] >>> NaN
				d1[1] = d0[1] + k[i2][1] >>> NaN
				if(d1[1] < d0[1] || d1[1] < k[i2][1]) d1[0] = ++d1[0] >>> NaN

				t1[0] = d1[0] + w[i2][0] >>> NaN
				t1[1] = d1[1] + w[i2][1] >>> NaN
				if(t1[1] < d1[1] || t1[1] < w[i2][1]) t1[0] = ++t1[0] >>> NaN

				d0[0] = (a[0] & b[0] ^ a[0] & c[0] ^ b[0] & c[0])
				d0[1] = (a[1] & b[1] ^ a[1] & c[1] ^ b[1] & c[1])
				d0[0] >>>= NaN
				d0[1] >>>= NaN

				d1[0] = ((a[1] << 4 | a[0] >>> 28) ^ (a[0] << 30 | a[1] >>> 2) ^ (a[0] << 25 | a[1] >>> 7))
				d1[1] = ((a[0] << 4 | a[1] >>> 28) ^ (a[1] << 30 | a[0] >>> 2) ^ (a[1] << 25 | a[0] >>> 7))
				d1[0] >>>= NaN
				d1[1] >>>= NaN

        h = g
        g = f
        f = e

		      e = [ d[0] + t1[0] >>> NaN, d[1] + t1[1] >>> NaN ]
					if(e[1] < d[1] || e[1] < t1[1]) e[0] = ++e[0] >>> NaN

        d = c
        c = b
        b = a

        v0 = [ t1[0] + d1[0] >>> NaN, t1[1] + d1[1] >>> NaN ]
				if(v0[1] < t1[1] || v0[1] < d1[1]) v0[0] = ++v0[0] >>> NaN

        a = [ v0[0] + d0[0] >>> NaN, v0[1] + d0[1] >>> NaN]
				if(a[1] < v0[1] || a[1] < d0[1]) a[0] = ++a[0] >>> NaN
			}

			d0[0]	= h0[0] >>> NaN
			d0[1] = h0[1] >>> NaN
      h0 		= [ d0[0] + a[0] >>> NaN, d0[1] + a[1] >>> NaN ]
			if(h0[1] < d0[1] || h0[1] < a[1]) h0[0] = ++h0[0] >>> NaN

			d0[0]	= h1[0] >>> NaN
			d0[1] = h1[1] >>> NaN
      h1 		= [ d0[0] + b[0] >>> NaN, d0[1] + b[1] >>> NaN ]
			if(h1[1] < d0[1] || h1[1] < b[1]) h1[0] = ++h1[0] >>> NaN

			d0[0]	= h2[0] >>> NaN
			d0[1] = h2[1] >>> NaN
      h2 		= [ d0[0] + c[0] >>> NaN, d0[1] + c[1] >>> NaN ]
			if(h2[1] < d0[1] || h2[1] < c[1]) h2[0] = ++h2[0] >>> NaN

			d0[0]	= h3[0] >>> NaN
			d0[1] = h3[1] >>> NaN
      h3 		= [ d0[0] + d[0] >>> NaN, d0[1] + d[1] >>> NaN ]
			if(h3[1] < d0[1] || h3[1] < d[1]) h3[0] = ++h3[0] >>> NaN

			d0[0]	= h4[0] >>> NaN
			d0[1] = h4[1] >>> NaN
      h4 		= [ d0[0] + e[0] >>> NaN, d0[1] + e[1] >>> NaN ]
			if(h4[1] < d0[1] || h4[1] < e[1]) h4[0] = ++h4[0] >>> NaN

			d0[0]	= h5[0] >>> NaN
			d0[1] = h5[1] >>> NaN
      h5 		= [ d0[0] + f[0] >>> NaN, d0[1] + f[1] >>> NaN ]
			if(h5[1] < d0[1] || h5[1] < f[1]) h5[0] = ++h5[0] >>> NaN

			d0[0]	= h6[0] >>> NaN
			d0[1] = h6[1] >>> NaN
      h6 		= [ d0[0] + g[0] >>> NaN, d0[1] + g[1] >>> NaN ]
			if(h6[1] < d0[1] || h6[1] < g[1]) h6[0] = ++h6[0] >>> NaN

			d0[0]	= h7[0] >>> NaN
			d0[1] = h7[1] >>> NaN
      h7 		= [ d0[0] + h[0] >>> NaN, d0[1] + h[1] >>> NaN ]
			if(h7[1] < d0[1] || h7[1] < h[1]) h7[0] = ++h7[0] >>> NaN
		}

		h = [
      h0[0] >>> 24, h0[0] >>> 16 & 0xff, h0[0] >> 8 & 0xff, h0[0] & 0xff,
      h0[1] >>> 24, h0[1] >>> 16 & 0xff, h0[1] >> 8 & 0xff, h0[1] & 0xff,
      h1[0] >>> 24, h1[0] >>> 16 & 0xff, h1[0] >> 8 & 0xff, h1[0] & 0xff,
      h1[1] >>> 24, h1[1] >>> 16 & 0xff, h1[1] >> 8 & 0xff, h1[1] & 0xff,
      h2[0] >>> 24, h2[0] >>> 16 & 0xff, h2[0] >> 8 & 0xff, h2[0] & 0xff,
      h2[1] >>> 24, h2[1] >>> 16 & 0xff, h2[1] >> 8 & 0xff, h2[1] & 0xff,
      h3[0] >>> 24, h3[0] >>> 16 & 0xff, h3[0] >> 8 & 0xff, h3[0] & 0xff,
      h3[1] >>> 24, h3[1] >>> 16 & 0xff, h3[1] >> 8 & 0xff, h3[1] & 0xff,
      h4[0] >>> 24, h4[0] >>> 16 & 0xff, h4[0] >> 8 & 0xff, h4[0] & 0xff,
      h4[1] >>> 24, h4[1] >>> 16 & 0xff, h4[1] >> 8 & 0xff, h4[1] & 0xff,
      h5[0] >>> 24, h5[0] >>> 16 & 0xff, h5[0] >> 8 & 0xff, h5[0] & 0xff,
      h5[1] >>> 24, h5[1] >>> 16 & 0xff, h5[1] >> 8 & 0xff, h5[1] & 0xff
		]

		if(!s384)
      h.push(	h6[0] >>> 24, h6[0] >>> 16 & 0xff, h6[0] >> 8 & 0xff, h6[0] & 0xff,
      				h6[1] >>> 24, h6[1] >>> 16 & 0xff, h6[1] >> 8 & 0xff, h6[1] & 0xff,
      				h7[0] >>> 24, h7[0] >>> 16 & 0xff, h7[0] >> 8 & 0xff, h7[0] & 0xff,
      				h7[1] >>> 24, h7[1] >>> 16 & 0xff, h7[1] >> 8 & 0xff, h7[1] & 0xff)

		return new jsl.Data.Blob(h)
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.hmac = function(data, key, hash) {
		try {
			var h, k, a, b, c, ds//!
			if(arguments.length < 1 || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(data, "t(s,al,Blob)", "data")
			if(arguments.length === 2)	jsl.validate(key, 	"t(s,al,Blob)", "key")
			if(arguments.length === 3)	jsl.validate(hash, 	"si(sha1,md5)", "hash")//!

			h 	= hash ? hash.toLowerCase() : this.get("hmac.hash")
			k		= key ? jsl.Data.Blob.toArray(key) : []
			k		= k.length > 64 ? this[h](k).__bs : k
			ds	= jsl.Data.Blob.toArray(data)

			b = []
			c = []
			for(a = 0; a < 64; a++) {
				b[a] = k[a] ^ 0x36
				c[a] = k[a] ^ 0x5c
			}

			return this[h](c.concat(this[h](b.concat(ds)).__bs))
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.key = function(password, options) {
		try {
			var ops, s, c, ks, pwd, a, l, n, k, k1, k2, b, sl, push, d, e, f//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(password, "s+", "password")
			if(arguments.length === 2)	jsl.validate(options, "t(i++,o)", "options")//!

			ops = jsl.isNumber(options) ? { size: options } : (options || {})
			s		= ops.salt 	!= null 		? ops.salt 					: this.get("key.salt")
			c		= ops.count	!= null 		? ops.count 				: this.get("key.count")
			ks	= ops.size 	!= null 		? ops.size 					: this.get("key.size")

			//!count 32bit
			jsl.validate(s	, "t(s+,al,Blob)"		, "options.salt")
			jsl.validate(c	, "i[1,4294967295]"	, "options.count")
			jsl.validate(ks	, "i[1,1310700]"		, "options.size")//!20 * 65535

			s = jsl.Data.Blob.toArray(s)//!
			if(!s.length)	throw jsl.ParamError("BadValue:options.salt")//!

			s.push(0, 0)
			push 	= Array.prototype.push
			sl 		= s.length

			pwd = []
    	for(a = b = 0, l = password.length; a < l; a++) {
				n	= password.charCodeAt(a)
    		if(n > 255) pwd[b++] = n >>> 8
    		pwd[b++] = n & 0xff
    	}

			pwd	= pwd.length > 64 ? this.sha1(pwd).__bs : pwd
     	l 	= Math.ceil(ks / 20)
    	k 	= []
			e 	= []
			f 	= []

			for(d = 0; d < 64; d++) {
				e[d] = pwd[d] ^ 0x36
				f[d] = pwd[d] ^ 0x5c
			}

    	for(a = 1; a <= l; a++) {

    		s[sl]			 = a >>> 8//max-l: 65535
    		s[sl + 1]  = a & 0xff
    		k1 		= k2 = this.hmac(s, pwd, "sha1").__bs

    		for(b = 1; b < c; b++) {

					k1 = this.sha1(f.concat(this.sha1(e.concat(k1)).__bs)).__bs

    			k2[0] 	^= k1[0]; 	k2[1]		^= k1[1]; 	k2[2] 	^= k1[2];		k2[3] 	^= k1[3]
    			k2[4] 	^= k1[4];		k2[5] 	^= k1[5];		k2[6] 	^= k1[6]; 	k2[7] 	^= k1[7]
    			k2[8] 	^= k1[8];		k2[9] 	^= k1[9];		k2[10] 	^= k1[10]; 	k2[11] 	^= k1[11]
    			k2[12] 	^= k1[12]; 	k2[13] 	^= k1[13];	k2[14] 	^= k1[14]; 	k2[15] 	^= k1[15]
    			k2[16] 	^= k1[16];	k2[17]	^= k1[17]; 	k2[18] 	^= k1[18];	k2[19] 	^= k1[19]
    		}

    		push.apply(k, k2)
    	}

			return new jsl.Data.Blob(k.slice(0, ks))
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.aes.encrypt = function(data, key, options) {
		try {
			var ops, sz, md, pd, iv, bs, sbx, rc, nk, nr, ds, bk, n, k, w, a, l, b, c, d, e0, e1, e2, e3, _0, _1, _2, _3, dec

			//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(data	, "t(s,al,Blob)", "data")
			jsl.validate(key	, "t(s,al,Blob)", "key")
			if(arguments.length === 3)	jsl.validate(options, "t(o,i++)", "options")//!

			ops	= jsl.isNumber(options) ? { size: options } : (options || {})
			sz	= ops.size 		!= null 	? ops.size					: jsl.Crypto.get("aes.size")
			md	= ops.mode 		!= null 	? ops.mode					: jsl.Crypto.get("aes.mode")
			iv	= ops.iv			!= null 	?	ops.iv 						: jsl.Crypto.get("aes.iv")
			pd	= ops.padding	!= null 	? ops.padding				: jsl.Crypto.get("aes.padding")
			bs 	= jsl.Data.Blob.toArray(data)

			//!
			jsl.validate(md, "si(ECB,CBC,CFB,OFB,CTR)", "options.mode")
			jsl.validate(iv, "t(s+,al,Blob)", "options.iv")
			jsl.validate(pd, "si(pkcs7,ansiX923,iso10126,zero,no)", "options.padding")
			jsl.validate(sz, "ns(128,192,256)", "options.size")

			if(jsl.Data.Blob.toArray(iv).length !== 16)								throw jsl.ParamError("BadValue:options.iv")
			if(!jsl.Data.Blob.toArray(key).length)										throw jsl.ParamError("crypto.aes.EmptyKey")
			if(md.match(/ecb|cbc/i) && bs.length % 16 && pd == "no")	throw jsl.ParamError("crypto.aes.BadPadding:" + md)//!

			//0-init
			//---------------------------------
			sbx	= this.__sbx
			rc	= this.__rc
			_0	= this.__0
			_1	= this.__1
			_2	= this.__2
			_3	= this.__3

			iv 	= jsl.Data.Blob.toArray(iv)
			md 	= md.toUpperCase()
			md	= { ECB: 0, CBC: 1, CFB: 2, OFB: 3, CTR: 4 }[md]
			nk	= { 128: 4	, 192: 6	, 256: 8 	}[sz]
			nr	= { 128: 10	, 192: 12	, 256: 14 }[sz]
			dec	= this.__dec
			bk	= iv
			ds 	= []

			//0.1-key normalization and data padding
			//---------------------------------
			k	= jsl.Data.Blob.toArray(key)
			if(sz / 8 !== k.length)	k = jsl.Crypto.key(jsl.Data.Blob.toString(k), sz / 8).__bs

			if((!md || md === 1) && pd != "no")
				pd = this.__pad(bs, pd)

			//1-aes: key expansion
			//---------------------------------
			w = this.__ek(k, nk, nr)

			for(a = 0, l = bs.length; a < l; a += 16) {

				n = a + 16
				c	= 0

				//block mode
				//---------------------------------
				if(!md)												bk = bs.slice(a, n)
				else if(md === 1)							for(b = a; b < n; b++)	bk[c++] = bs[b] ^ (a >= 16 ? ds[b - 16] : iv[b])
				else if(md === 2 && a >= 16)	bk = (dec ? bs : ds).slice(a - 16, a)

				//1.2-aes: first round key
				//---------------------------------
				for(b = a, c = 0; b < n; b += 4, c++) {
					ds[b] 		= bk[c * 4]			^ w[c][0]
					ds[b + 1]	= bk[c * 4 + 1]	^ w[c][1]
					ds[b + 2]	= bk[c * 4 + 2]	^ w[c][2]
					ds[b + 3]	= bk[c * 4 + 3]	^ w[c][3]
				}

				for(b = 0; b < nr; b++) {

					//1.3-aes: bytes substitution
					//---------------------------------
					for(c = a; c < n; c++)
						ds[c] = sbx[ds[c]]

					//1.4-aes: shift rows
					//---------------------------------
					c = a + 1
					d = ds[c]
					ds[c] 			= ds[c + 4]
					ds[c + 4] 	= ds[c + 8]
					ds[c + 8] 	= ds[c + 12]
					ds[c + 12] 	= d

					d = ds[c + 1]
					ds[c + 1] = ds[c + 9]
					ds[c + 9] = d

					d = ds[c + 5]
					ds[c + 5]		= ds[c + 13]
					ds[c + 13]	= d

					d = ds[c + 2]
					ds[c + 2] 	= ds[c + 14]
					ds[c + 14] 	= ds[c + 10]
					ds[c + 10] 	= ds[c + 6]
					ds[c + 6] 	= d

					//1.5-aes: mix columns
					//---------------------------------
					if(b < nr - 1)
						for(c = a; c < n; c += 4) {

							e0 	= ds[c]
							e1 	= ds[c + 1]
							e2	= ds[c + 2]
							e3 	= ds[c + 3]

							ds[c] 		= _2[e0] 	^ _3[e1] 	^ e2 			^ e3
							ds[c + 1] = e0 			^ _2[e1] 	^ _3[e2] 	^ e3
							ds[c + 2] = e0 			^ e1 			^ _2[e2] 	^ _3[e3]
							ds[c + 3] = _3[e0] 	^ e1 			^ e2 			^ _2[e3]
						}

					//1.6-aes: round key
					//---------------------------------
					for(c = a, d = 0; c < n; c += 4, d++) {
						ds[c] 		^= w[d + (b + 1) * 4][0]
						ds[c + 1]	^= w[d + (b + 1) * 4][1]
						ds[c + 2]	^= w[d + (b + 1) * 4][2]
						ds[c + 3]	^= w[d + (b + 1) * 4][3]
					}
				}

				//block mode
				//---------------------------------
				if(md > 1) {

					//next input block
					if(md === 3)
						bk = ds.slice(a, n)
					else if(md === 4) {
						iv 			= (bk[12] << 24 | bk[13] << 16 | bk[14] << 8 | bk[15]) + 1
						bk[12] 	= iv >>> 24	& 0xff
						bk[13] 	= iv >>> 16 & 0xff
						bk[14] 	= iv >>> 8 	& 0xff
						bk[15] 	= iv & 0xff
					}

					//output block
					for(b = a; b < n; b++) ds[b] ^= bs[b]
				}
			}

			//@sys: IE6 - finally doesn't works if an exception is trown inside the catch block
			if(pd > 0) bs.splice(bs.length - pd, pd)
			if(md > 1) ds.splice(ds.length - (n = ds.length - bs.length), n)
			return new jsl.Data.Blob(ds)
		}
		catch(e) {
			if(pd > 0) bs.splice(bs.length - pd, pd)
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.aes.decrypt = function(data, key, options) {
		try {
			var ops, sz, md, pd, iv, bs, sbx, rc, _9, _B, _D, _E, nk, nr, ds, n, a, b, c, d, l, k, w, e0, e1, e2, e3

			//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()
			jsl.validate(data	, "t(s,al,Blob)", "data")
			jsl.validate(key	, "t(s,al,Blob)", "key")
			if(arguments.length === 3)	jsl.validate(options, "t(o,i++)", "options")//!

			ops	= jsl.isNumber(options) ? { size: options } : (options || {})
			sz	= ops.size 		!= null 	? ops.size					: jsl.Crypto.get("aes.size")
			md	= ops.mode 		!= null 	? ops.mode					: jsl.Crypto.get("aes.mode")
			iv	= ops.iv			!= null 	?	ops.iv 						: jsl.Crypto.get("aes.iv")
			pd	= ops.padding	!= null 	? ops.padding				: jsl.Crypto.get("aes.padding")

			//!
			jsl.validate(md, "si(ECB,CBC,CFB,OFB,CTR)", "options.mode")
			jsl.validate(iv, "t(s+,al,Blob)", "options.iv")
			jsl.validate(pd, "si(pkcs7,ansiX923,iso10126,zero,no)", "options.padding")
			jsl.validate(sz, "ns(128,192,256)", "options.size")

			if(jsl.Data.Blob.toArray(iv).length !== 16)	throw jsl.ParamError("BadValue:options.iv")
			if(!jsl.Data.Blob.toArray(key).length)			throw jsl.ParamError("crypto.aes.EmptyKey")//!

			//symmetric encryption
			//---------------------------------
			if(!md.search(/cfb/i))
				try 			{	this.__dec = true; ds = this.encrypt.apply(this, arguments); this.__dec = false; return ds }
				catch(e) 	{	this.__dec = false; throw e }
			else if(!md.search(/ofb|ctr/i))
				return this.encrypt.apply(this, arguments)

			//0-init
			//---------------------------------
			bs 	= jsl.Data.Blob.toArray(data)
			sbx	= this.__sbxi
			rc	= this.__rc
			_9	= this.__9
			_B	= this.__B
			_D	= this.__D
			_E	= this.__E

			iv 	= jsl.Data.Blob.toArray(iv)
			md 	= md.toUpperCase()
			md	= { ECB: 0, CBC: 1, CFB: 2, OFB: 3, CTR: 4 }[md]
			nk	= { 128: 4	, 192: 6	, 256: 8 	}[sz]
			nr	= { 128: 10	, 192: 12	, 256: 14 }[sz]
			ds 	= []

			//0.1-key normalization
			//---------------------------------
			k	= jsl.Data.Blob.toArray(key)
			if(sz / 8 !== k.length)	k = jsl.Crypto.key(jsl.Data.Blob.toString(k), sz / 8).__bs

			//1-key expansion
			//---------------------------------
			w	= this.__ek(k, nk, nr)

			for(a = 0, l = bs.length; a < l; a += 16) {

				n = a + 16

				//1.2-aes: first round key
				//---------------------------------
				for(b = a, c = 4 * nr; b < n; b += 4, c++) {
					ds[b] 		= bs[b]			^ w[c][0]
					ds[b + 1]	= bs[b + 1]	^ w[c][1]
					ds[b + 2]	= bs[b + 2]	^ w[c][2]
					ds[b + 3]	= bs[b + 3]	^ w[c][3]
				}

				for(b = nr - 1; b >= 0; b--) {

					//1.3-aes: shift rows
					//---------------------------------
					c = a + 1
					d = ds[c + 12]
					ds[c + 12] 	= ds[c + 8]
					ds[c + 8] 	= ds[c + 4]
					ds[c + 4] 	= ds[c]
					ds[c] 			= d

					d = ds[c + 1]
					ds[c + 1] = ds[c + 9]
					ds[c + 9] = d

					d = ds[c + 5]
					ds[c + 5]		= ds[c + 13]
					ds[c + 13]	= d

					d = ds[c + 2]
					ds[c + 2] 	= ds[c + 6]
					ds[c + 6] 	= ds[c + 10]
					ds[c + 10] 	= ds[c + 14]
					ds[c + 14] 	= d

					//1.4-aes: bytes substitution
					//---------------------------------
					for(c = a; c < n; c++)
						ds[c] = sbx[ds[c]]

					//1.5-aes: round key
					//---------------------------------
					for(c = a, d = 0; c < n; c += 4, d++) {
						ds[c] 		^= w[d + b * 4][0]
						ds[c + 1]	^= w[d + b * 4][1]
						ds[c + 2]	^= w[d + b * 4][2]
						ds[c + 3]	^= w[d + b * 4][3]
					}

					//1.6-aes: mix columns
					//---------------------------------
					if(b)
						for(c = a; c < n; c += 4) {

							e0 	= ds[c]
							e1 	= ds[c + 1]
							e2	= ds[c + 2]
							e3 	= ds[c + 3]

							ds[c] 		= _E[e0] ^ _B[e1] ^ _D[e2] ^ _9[e3]
							ds[c + 1] = _9[e0] ^ _E[e1] ^ _B[e2] ^ _D[e3]
							ds[c + 2]	= _D[e0] ^ _9[e1] ^ _E[e2] ^ _B[e3]
							ds[c + 3] = _B[e0] ^ _D[e1] ^ _9[e2] ^ _E[e3]
						}
				}

				//block mode
				//---------------------------------
				if(md === 1)	for(b = a; b < n; b++) ds[b] ^= (a >= 16 ? bs[b - 16] : iv[b])
			}

			//2-completion tasks
			//---------------------------------
			if(pd != "no") this.__unpad(ds, pd)
			return new jsl.Data.Blob(ds)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.aes.__ek = function(k, nk, nr) {
		var w, a, t, rc, sbx, n, l

		w		= []
		rc	= this.__rc
		sbx	= this.__sbx
		for(a = 0; a < nk; a++)
			w[a] = k[4 * a] << 24 | k[4 * a + 1] << 16 | k[4 * a + 2] << 8 | k[4 * a + 3]

		n = 4 * (nr + 1)
		while(a < n) {
			t = w[a - 1]

			if(!(a % nk)) {
				t = t << 8 | t >>> 24
				t = sbx[t >>> 24] << 24 | sbx[t >>> 16 & 0xFF] << 16 | sbx[t >>> 8 & 0xFF] << 8 | sbx[t & 0xFF]
				t = t ^ rc[a / nk]
			}
			else
				if(nk > 6 && a % nk === 4)
					t = sbx[t >>> 24] << 24 | sbx[t >>> 16 & 0xFF] << 16 | sbx[t >>> 8 & 0xFF] << 8 | sbx[t & 0xFF]

			w[a] = w[a++ - nk] ^ t
		}

		for(a = 0, l = w.length; a < l; a++)
			w[a] = [ w[a] >>> 24,  w[a] >>> 16 & 0xFF, w[a] >>> 8 & 0xFF, w[a] & 0xFF ]

		return w
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.aes.__pad = function(bs, pd) {
		var n, i

		n = i = 16 - bs.length % 16

		switch(pd) {
			case "pkcs7":
				while(i--) bs.push(n)
				break
			case "ansix923":
				while(--i) bs.push(0)
				bs.push(n)
				break
			case "iso10126":
				while(--i) bs.push(Math.round(Math.random() * 255))
				bs.push(n)
				break
			case "zero":
				while(i--) bs.push(0)
		}

		return n
	}
	//-------------------------------------------------------------------------------
	jsl.Crypto.aes.__unpad = function(bs, pd) {
		var n, i

		switch(pd) {
			case "pkcs7":
			case "ansix923":
			case "iso10126":
				n = bs[bs.length - 1]//!
				if(isNaN(n) || n > 16)	throw jsl.ConfigError("crypto.aes.DecryptError")//!
				bs.splice(bs.length - n, n)
				break
			case "zero":
				n = i = bs.length - 1
				while(bs[i] === 0) i--

				n -= i
				bs.splice(bs.length - n, n)
		}
	}
